package com.iot08.admin.service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.iot08.admin.utils.AlipayUtil;
import com.iot08.admin.utils.ApplePayUtil;
import com.iot08.admin.utils.WxPayUtil;
import com.iot08.apple.pay.model.JWSTransactionDecodedPayload;
import com.iot08.common.entity.admin.RefundApply;
import com.iot08.common.entity.app.PayOrderInfo;
import com.iot08.common.entity.app.VipMember;
import com.iot08.common.response.Response;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * @author cwj
 * @description
 * @date 2025/1/22 9:59
 **/
@Slf4j
@Service
public class PaymentService extends BaseService<PayOrderInfo> {

    @Value("${pay.call.back.notify.request.way}")
    private String callBackNotifyRequestWay;

    @Value("${wxpay.pay.refund.notify.domian}")
    private String domaim;

    @Resource
    private WxPayUtil wxPayUtil;

    @Resource
    private AlipayUtil alipayUtil;

    @Resource
    private ApplePayUtil applePayUtil;

    @Resource
    private RefundApplyService refundApplyService;

    @Resource
    private VipMemberService vipMemberService;

    @Resource
    private PayOrderInfoService payOrderInfoService;
    
    /**
     * @description 订单退款申请
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.response.Response<java.lang.Object>
     * @date @time 2025/1/22 10:32
     **/
    public Response<Object> refundApply(String orderId) {
        //查询支付订单记录
        PayOrderInfo payOrderInfo = this.findById(new ObjectId(orderId));
        if(ObjectUtils.isEmpty(payOrderInfo) || !payOrderInfo.getOrderStatus().equals(1)){
            return Response.failedResponse("订单不存在或支付失败，亦或已退款");
        }
        //查询订单是否已经存在退款中的或已经退款成功的退款申请
        if(refundApplyService.queryrRefundApplyExists(orderId)){
            return Response.failedResponse("订单已经在退款中或已退款");
        }
        String refundReason = "会员充值退款";
        if ("wechatPay".equals(payOrderInfo.getPaymentMethod())) {
            //微信退款
            try {
                String notifyUrl = String.format("%s://%s/getway/accounts/wx_refund",callBackNotifyRequestWay, domaim);
                Integer refundAmount = payOrderInfo.getRealPayAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN).intValue();
                Integer total = payOrderInfo.getPayAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN).intValue();
                //先保存退款申请记录
                RefundApply refundApply = refundApplyService.saveRefundApplyByOrderId(payOrderInfo.getTransactionId(),
                        orderId,"wechatRefund",payOrderInfo.getOrderType(),payOrderInfo.getProductType(),
                        refundReason,payOrderInfo.getPayAmount());
                JSONObject jsonObject = wxPayUtil.refundApply(payOrderInfo.getTransactionId(),refundReason,notifyUrl,refundAmount, total,payOrderInfo.getCurrency(),refundApply.getId());
                log.info("退款申请接口响应数据：{}",jsonObject);
                if(!ObjectUtils.isEmpty(jsonObject)){
                   //更新退款申请记录
                   refundApplyService.updateRefundApplyByJson(jsonObject);
                } else {
                    log.info("退款申请请求失败");
                    return Response.failedResponse("退款申请失败");
                }
            } catch (Exception e) {
                log.error("微信退款申请发送异常，异常信息为：{}",e.getMessage());
                return Response.failedResponse("退款申请失败");
            }
        } else if("alipay".equals(payOrderInfo.getPaymentMethod())) {
            try {
                //支付宝退款
                String notifyUrl = String.format("%s://%s/getway/accounts/alipay_payment",callBackNotifyRequestWay, domaim);
                String refundAmount = payOrderInfo.getRealPayAmount().toString();
                //保存支付宝退款申请
                RefundApply refundApply = refundApplyService.saveRefundApplyByOrderId(payOrderInfo.getTransactionId(), orderId,"alipayRefund",
                        payOrderInfo.getOrderType(),payOrderInfo.getProductType(),refundReason,payOrderInfo.getPayAmount());
                AlipayTradeRefundResponse refundRsp = alipayUtil.refundApply(payOrderInfo.getTransactionId(),payOrderInfo.getId(),refundAmount,
                        refundReason,refundApply.getId(),notifyUrl);
                if(!ObjectUtils.isEmpty(refundRsp) && refundRsp.isSuccess()) {
                    //更新退款申请记录
                    refundApplyService.updateRefundApplyByAlipayTradeRefund(refundRsp,refundApply.getId());
                } else {
                    return Response.failedResponse("退款申请失败");
                }
            } catch (AlipayApiException e) {
                log.error("退款申请失败，失败原因为：{}",e.getMessage());
                return Response.failedResponse("退款申请失败");
            }
        } else if("applePay".equals(payOrderInfo.getPaymentMethod())) {
              //苹果支付退款
        } else {
            log.error("订单支付类型不存在");
            return Response.failedResponse("订单的支付类型错误，无法退款，请联系管理员");
        }
        return Response.successResponse("退款申请成功");
    }


    /**
     * @description 查询苹果支付订单的订单状态，如果未支付的订单查询出已支付,也需要更新订单及会员信息，如果已退款则更新会员信息
     * @author cwj
     * @param [orderId]
     * @return com.iot08.common.response.Response<java.lang.Object>
     * @date @time 2025/2/24 15:57
     **/
    public Response<Object> queryApplyPayOrderStatus(String orderId) {
        log.info("苹果支付查询订单请求参数{}",orderId);
        //查询订单状态是否已经被更新了，如果被更新了，说明已经通过通知更新了会员信息
        PayOrderInfo payOrderInfo = this.findById(new ObjectId(orderId));
        if(ObjectUtils.isEmpty(payOrderInfo) || StringUtils.isEmpty(payOrderInfo.getTransactionId())){
            log.info("苹果支付订单未找到");
            return Response.failedResponse("支付订单不存在");
        }
        //直接查询订单状态信息
        JWSTransactionDecodedPayload jwsTransactionDecodedPayload = applePayUtil.queryAppleTransactionInfo(payOrderInfo.getTransactionId());
        if (ObjectUtils.isEmpty(jwsTransactionDecodedPayload)) {
            log.info("查询苹果支付订单不存在或交易失败");
            return Response.failedResponse("Apple Pay支付订单查询失败");
        }
        dealwithPayUpdate(jwsTransactionDecodedPayload, payOrderInfo, orderId);
        //订单存在且订单目前为已支付，订单之前没退款，现在退款了，则更新支付订单及会员信息
        dealwithRefundUpdate(jwsTransactionDecodedPayload, payOrderInfo);
        return Response.successResponse();
    }
    
    /**
     * @description 查询苹果订单支付信息，更新支付订单状态及会员状态
     * @author cwj
     * @param []
     * @return boolean
     * @date @time 2025/2/26 11:26
     **/
    public boolean queryUpdateApplePayOrderInfo() {
        //查询支付状态为0或1的且tranactionId不为空的苹果支付订单信息
        List<PayOrderInfo> payOrderInfos = payOrderInfoService.queryApplePayOrderInfo();
        for (PayOrderInfo payOrderInfo : payOrderInfos) {
            //直接查询订单状态信息
            JWSTransactionDecodedPayload jwsTransactionDecodedPayload = applePayUtil.queryAppleTransactionInfo(payOrderInfo.getTransactionId());
            if (ObjectUtils.isEmpty(jwsTransactionDecodedPayload)) {
                log.info("查询苹果支付订单不存在或交易失败");
                continue;
            }
            //处理支付更新
            dealwithPayUpdate(jwsTransactionDecodedPayload, payOrderInfo, payOrderInfo.getId());
            //订单存在且订单目前为已支付，订单之前没退款，现在退款了，则更新支付订单及会员信息
            dealwithRefundUpdate(jwsTransactionDecodedPayload, payOrderInfo);
        }
        return true;
    }

    /**
     * @description 处理支付更新
     * @author cwj
     * @param [jwsTransactionDecodedPayload, payOrderInfo, payOrderInfo1]
     * @return void
     * @date @time 2025/2/26 11:51
     **/
    private void dealwithPayUpdate(JWSTransactionDecodedPayload jwsTransactionDecodedPayload, PayOrderInfo payOrderInfo, String payOrderInfo1) {
        Long purchaseDate = jwsTransactionDecodedPayload.getPurchaseDate();
        String purchaseDateStr = null;
        if (!ObjectUtils.isEmpty(purchaseDate)) {
            purchaseDateStr = DateUtil.stampToDateStr(purchaseDate, DateUtil.FORMAT_1);
        }
        //判断订单是否支付成功，判断订单信息是否存在，判断订单是否为未支付
        if (isApplePaySuccessfully(jwsTransactionDecodedPayload) && payOrderInfo.getOrderStatus().equals(0)) {
            //说明订单支付成功，更新订单信息和会员信息
            payOrderInfoService.updatePayOrderInfo(payOrderInfo1, payOrderInfo.getTransactionId(), purchaseDateStr, null, null, null, 1, 1, "订单已支付成功");
            //更新会员信息
            vipMemberService.updateVipMemberInfo(payOrderInfo, 1);
        }
    }

    /**
     * @description 处理退款更新
     * @author cwj
     * @param [jwsTransactionDecodedPayload, payOrderInfo]
     * @return void
     * @date @time 2025/2/26 11:52
     **/
    private void dealwithRefundUpdate(JWSTransactionDecodedPayload jwsTransactionDecodedPayload, PayOrderInfo payOrderInfo) {
        if(checkRefundSuccess(jwsTransactionDecodedPayload) && payOrderInfo.getOrderStatus().equals(1)) {
            //更新支付订单状态为退款状态
            this.updatePayOrderRefundStatus(payOrderInfo.getId(),3,3);
            //查询会员信息，有效无效都查询
            VipMember vipMember = vipMemberService.queryVipMemberByOpenId(payOrderInfo.getOpenid());
            PayOrderInfo secondPayOrderInfo;
            if(payOrderInfo.getId().equals(vipMember.getOrderid())){
                log.info("查询倒数第二个支付订单信息之前");
                //查询倒数第二个有效支付订单信息，如果存在，则将会员的订单信息更新为倒数第二个的订单信息
                secondPayOrderInfo = this.queryInverseSecondPayOrderInfo(payOrderInfo.getOpenid(), payOrderInfo.getId());
                log.info("查询倒数第二个支付订单信息之后，secondPayOrderInfo的数据为：{}",secondPayOrderInfo);
                //根据订单对应的产品类型，更新会员的有效期
                vipMemberService.updateVipMemberEffectTimeTypeOrderId(payOrderInfo.getOpenid(), payOrderInfo.getProductType(),
                        !ObjectUtils.isEmpty(secondPayOrderInfo), !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getId():null,
                        !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getProductType():null);
            } else {
                vipMemberService.updateVipMemberEffectTimeTypeOrderId(payOrderInfo.getOpenid(), payOrderInfo.getProductType()
                        ,false,null,null);
            }
        }
    }

    /**
     * @description 检查退款是否成功
     * @author cwj
     * @param [jwsTransactionDecodedPayload]
     * @return boolean
     * @date @time 2025/2/24 17:12
     **/
    public boolean checkRefundSuccess(JWSTransactionDecodedPayload jwsTransactionDecodedPayload) {
        return !ObjectUtils.isEmpty(jwsTransactionDecodedPayload.getRevocationDate()) && 
                !ObjectUtils.isEmpty(jwsTransactionDecodedPayload.getRawRevocationReason());
    }

    /**
     * @description 检查订单是否支付成功
     * @author cwj
     * @param [jtdp]
     * @return boolean
     * @date @time 2025/2/26 9:42
     **/
    public boolean isApplePaySuccessfully(JWSTransactionDecodedPayload jtdp) {
        // 交易 ID 存在、购买时间存在、未退款、订单已购买、 交易类型是购买
        return !StringUtils.isEmpty(jtdp.getTransactionId())
                && !ObjectUtils.isEmpty(jtdp.getPurchaseDate())
                && jtdp.getRevocationReason() == null
                && "PURCHASED".equals(jtdp.getInAppOwnershipType().getValue())
                && "PURCHASE".equals(jtdp.getTransactionReason().getValue());
    }

    /**
     * @description 更新支付订单信息
     * @author cwj
     * @param [orderId, orderStatus, paymentStatus]
     * @return void
     * @date @time 2025/2/24 17:21
     **/
    public void updatePayOrderRefundStatus(String orderId,Integer orderStatus, Integer paymentStatus) {
        Update update = new Update();
        update.set("orderStatus",orderStatus);
        update.set("paymentStatus",paymentStatus);
        update.set("updateTime",new Date());
        this.updateById(new ObjectId(orderId),update);
    }

    /**
     * @description 查询倒数第二个有效支付订单的信息
     * @author cwj
     * @param [openId, orderId]
     * @return com.iot08.common.entity.app.PayOrderInfo
     * @date @time 2025/2/24 17:22
     **/
    public PayOrderInfo queryInverseSecondPayOrderInfo(String openId,String orderId) {
        //组装查询条件
        Query query = new Query();
        query.addCriteria(Criteria.where("openid").is(openId).and("orderStatus").is(1).and("_id").ne(new ObjectId(orderId)));  // 查询条件
        query.with(Sort.by(Sort.Direction.DESC, "createTime")).limit(1);  // 按 createTime 降序排序
        return this.findOne(query);
    }

}
